package com.njcb.ams.factory.comm;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.njcb.ams.store.page.Page;
import com.njcb.ams.support.annotation.Trader;
import com.njcb.ams.support.exception.ExceptionCode;
import com.njcb.ams.support.exception.ExceptionUtil;
import com.njcb.ams.util.AmsDateUtils;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 全局信息,绑定此信息的线程在任意地方都能引用
 *
 * @author LIUYANLONG
 *
 */
public class DataBus implements Serializable {
	private static final long serialVersionUID = 1L;
	private static TransmittableThreadLocal<DataBus> threadLocal = new TransmittableThreadLocal<DataBus>();
	public static String KEY_GLOBAL_INFO = "AMS_GLOBAL_INFO";
	/**
	 * 交易代码
	 */
	private Trader trader;

	/**
	 * 用户ID
	 */
	private int userId;

	/**
	 * 用户属性 0真是用户 1虚拟用户
	 */
	private int userAttr = 1;

	/**
	 * 用户登录名
	 */
	private String loginName;

	/**
	 * 用户显示名
	 */
	private String userName;

	/**
	 * 用户角色代码
	 */
	private List<String> roleCodes;

	/**
	 * 用户机构号
	 */
	private String orgNo;

	/**
	 * 用户机构名称
	 */
	private String orgName;

	/**
	 * 分页信息 不序列号此属性
	 */
	private transient Page page;
	
	/**
	 * 分页结果 不序列号此属性,临时存放分页结果
	 */
	private transient Page resultPage;
	private transient Map<String, Object> attributes = new HashMap<String, Object>();

	public static int getUserId() {
		return getInstance().userId;
	}

	/**
	 * 交易日期 YYYYMMDD
	 * @return 交易日期
	 */
	public static String getBusiDate() {
		return AmsDateUtils.getBusiDate();
	}

	public static int getUserAttr() {
		return getInstance().userAttr;
	}

	public static String getUserName() {
		return getInstance().userName;
	}

	public static String getOrgName() {
		return getInstance().orgName;
	}

	public static String getLoginName() {
		return getInstance().loginName;
	}

	public static List<String> getRoleCodes() {
		return getInstance().roleCodes;
	}

	public static String getOrgNo() {
		return getInstance().orgNo;
	}

	public void setUserId(int userId) {
		this.userId = userId;
	}

	public void setUserAttr(int userAttr) {
		this.userAttr = userAttr;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public void setLoginName(String loginName) {
		this.loginName = loginName;
	}

	public void setOrgNo(String orgNo) {
		this.orgNo = orgNo;
	}

	public void setOrgName(String orgName) {
		this.orgName = orgName;
	}

	public void setRoleCodes(List<String> roleCodes) {
		this.roleCodes = roleCodes;
	}

	public void setPage(Page page) {
		this.page = page;
	}

	public Page getPage() {
		return page;
	}

	public void setResultPage(Page page) {
		this.resultPage = page;
	}

	public Page getResultPage() {
		return resultPage;
	}

	public static void setTrader(Trader trader) {
		threadLocal.set(Optional.ofNullable(threadLocal.get()).orElse(new DataBus()));
		threadLocal.get().trader = trader;
	}

	public static Trader getTrader() {
		return getInstance().trader;
	}

	/**
	 * 获取数据实例 方法功能描述：
	 * @return 实例
	 */
	public static DataBus getInstance() {
		DataBus globalInfo = threadLocal.get();
		if (null == globalInfo) {
			ExceptionUtil.throwAppException(ExceptionCode.NOTFOUND_DATA_BUS);
		}
		return globalInfo;
	}

	public static DataBus getUncheckInstance() {
		DataBus globalInfo = threadLocal.get();
		return globalInfo;
	}

	/**
	 * DataBus是否为空
	 * 
	 * @return 是否空
	 */
	public static Boolean isNotNull() {
		if (null == threadLocal.get()) {
			return false;
		} else {
			return true;
		}
	}

	public static void setCurrentInstance(DataBus globalInfo) {
		threadLocal.set(globalInfo);
	}

	public static void remove() {
		threadLocal.remove();
	}

	public static void clearAttributes() {
		if (null != threadLocal.get() && null != threadLocal.get().attributes) {
			threadLocal.get().attributes.clear();
		}
	}

	/**
	 * 方法功能描述：判断是否存在附加属性
	 * @return 是否空
	 */
	public static boolean attributeIsEmpty() {
		if (null == threadLocal.get()) {
			return true;
		}
		if (null == threadLocal.get().attributes || threadLocal.get().attributes.size() == 0) {
			return true;
		}
		return false;
	}

	public static void setAttribute(String name, Object value) {
		threadLocal.set(Optional.ofNullable(threadLocal.get()).orElse(new DataBus()));
		if (value != null) {
			threadLocal.get().attributes = Optional.ofNullable(threadLocal.get().attributes)
					.orElse(new HashMap<String, Object>());
			threadLocal.get().attributes.put(name, value);
		} else {
			removeAttribute(name);
		}
	}

	public void addAttribute(String name, Object value) {
		attributes = Optional.ofNullable(attributes).orElse(new HashMap<String, Object>());
		attributes.put(name, value);
	}

	public static Object getAttribute(String name) {
		return Optional.ofNullable(threadLocal.get()).map(bus -> bus.attributes).map(attr -> attr.get(name))
				.orElse(null);
	}

	public static Map<String, Object> getAttributes() {
		return Optional.ofNullable(threadLocal.get()).map(bus -> bus.attributes).orElse(null);
	}

	@SuppressWarnings("unchecked")
	public static <T> T getAttribute(String name, Class<T> clazz) {
		return (T) getAttribute(name);
	}

	public static <T> void setObject(T userInfo) {
		setAttribute(userInfo.getClass().getName(), userInfo);
	}

	@SuppressWarnings("unchecked")
	public static <T> T getObject(Class<T> clazz) {
		return (T) getAttribute(clazz.getName());
	}

	public static void removeAttribute(String name) {
		if (null != threadLocal.get().attributes) {
			threadLocal.get().attributes.remove(name);
		}
	}
}